package sonic.game;

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Scanner;
import java.util.concurrent.CopyOnWriteArrayList;

import javax.imageio.ImageIO;

import sonic.game.animation.Animation;
import sonic.game.character.Badnik;
import sonic.game.character.TriceratopsBadnik;
import sonic.game.character.WaspBadnik;
import sonic.game.item.GameItemRing;
import sonic.game.tile.Tile;
import sonic.game.util.Vector2D;

/**
 * Game Map
 * 
 * Loads and stores level data. Also keeps an animation cache for world geometry
 * 
 * @author RGreenlees
 *
 */

public class GameMap {

	public BufferedImage backgroundImage;
	
	/** Stores a cache of all world geometry tiles, as they don't have their own animation objects */
	public ArrayList<String> animCacheID = new ArrayList<String>();
	public ArrayList<Animation> animCache = new ArrayList<Animation>();
	
	/** mapTiles refers to all the tiles in the current level */ 
	public ArrayList<Tile> relevantTiles = new ArrayList<Tile>();
	
	/** tilesToDestroy and pendingTiles are held until the next loop, to avoid concurrent modification exceptions during the main game loop */
	public CopyOnWriteArrayList<Tile> tilesToDestroy = new CopyOnWriteArrayList<Tile>();
	public CopyOnWriteArrayList<Tile> pendingTiles = new CopyOnWriteArrayList<Tile>();
	
	/** Sonic will die if he falls below the Y map bounds, and the camera will not move beyond the X/Y bounds */
	public float mapBoundsY = 500.0f;
	public float mapBoundsX = 2000.0f;
	
	/** Where to start the player off */
	public Vector2D playerStart = new Vector2D();
	
	/** Read the supplied file and build the level up using the information inside */
	public GameMap(String mapFile)
	{
		try
		{
			Scanner reader = new Scanner(new File(mapFile));
			
			while(reader.hasNextLine())
			{
				String line = reader.nextLine();
				if(line.startsWith("#BACKGROUND:"))
				{
					try
					{
						backgroundImage = ImageIO.read(new File(line.substring(12)));
					}
					catch (IOException e)
					{
						e.printStackTrace();
					}
				}
				else if (line.startsWith("#PLAYERSTART:"))
				{
					playerStart.x = Integer.parseInt(line.substring(line.indexOf("LOCX=")+5, line.indexOf(";", line.indexOf("LOCX="))));
					playerStart.y = Integer.parseInt(line.substring(line.indexOf("LOCY=")+5, line.indexOf(";", line.indexOf("LOCY="))));
				}
				else if (line.startsWith("#TILEANIMDEF:"))
				{
					String animID;
					Animation anim;
					
					animID = line.substring(line.indexOf("ID=") + 3, line.indexOf(";"));
					anim = new Animation(Integer.parseInt(animID), false, line.substring(line.indexOf("IMG=")+4));
					addCachedAnim(animID, anim);
					
				}
				else if (line.startsWith("#TILEDEF:"))
				{
					int locX, locY;
					String id;
					
					id = line.substring(line.indexOf("ANIM=") + 5, line.indexOf(";"));
					locX = Integer.parseInt(line.substring(line.indexOf("LOCX=")+5, line.indexOf(";", line.indexOf("LOCX="))));
					locY = Integer.parseInt(line.substring(line.indexOf("LOCY=")+5, line.indexOf(";", line.indexOf("LOCY="))));
					
					pendingTiles.add(new Tile(locX, locY, id));
				}
				else if (line.startsWith("#ITEMDEF:"))
				{
					float itemLocX, itemLocY;
					if(line.indexOf("RING") > -1)
					{
						itemLocX = Integer.parseInt(line.substring(line.indexOf("LOCX=")+5, line.indexOf(";", line.indexOf("LOCX="))));
						itemLocY = Integer.parseInt(line.substring(line.indexOf("LOCY=")+5, line.indexOf(";", line.indexOf("LOCY="))));
						GameItemRing newRing = new GameItemRing(new Vector2D(itemLocX, itemLocY));
						pendingTiles.add(newRing);
						newRing.updateBounds();
					}
				}
				else if (line.startsWith("#BADNIKDEF:"))
				{
					float badnikLocX, badnikLocY;
					Badnik newBadnik = null;
					
					badnikLocX = Integer.parseInt(line.substring(line.indexOf("LOCX=")+5, line.indexOf(";", line.indexOf("LOCX="))));
					badnikLocY = Integer.parseInt(line.substring(line.indexOf("LOCY=")+5, line.indexOf(";", line.indexOf("LOCY="))));
					Vector2D startLoc = new Vector2D(badnikLocX, badnikLocY);
					
					if(line.indexOf("WASP") > -1)
					{
						newBadnik = new WaspBadnik(startLoc);
					}
					else if (line.indexOf("TRICERATOPS") > -1)
					{
						newBadnik = new TriceratopsBadnik(startLoc);
					}
					
					if (newBadnik != null)
					{
						pendingTiles.add(newBadnik);
						newBadnik.updateBounds();
					}
				}
			}
			reader.close();
		}
		catch (FileNotFoundException e1)
		{
			e1.printStackTrace();
			System.exit(1);
		}
		
	}
	
	public Animation getCachedAnim(String identifier)
	{
		return animCache.get(animCacheID.indexOf(identifier));
	}
	
	public void addCachedAnim(String identifier, Animation newAnim)
	{
		animCacheID.add(identifier);
		animCache.add(animCacheID.indexOf(identifier), newAnim);
	}
	
}
